﻿using Net.Chirash.Twitter.TwitterClient;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using Net.Chirash.Twitter.TwitterDatabase;

namespace TwitterClientTest
{


    /// <summary>
    ///TwitterLocalCommandTest のテスト クラスです。すべての
    ///TwitterLocalCommandTest 単体テストをここに含めます
    ///</summary>
    [TestClass()]
    public class TwitterLocalCommandTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///現在のテストの実行についての情報および機能を
        ///提供するテスト コンテキストを取得または設定します。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 追加のテスト属性
        // 
        //テストを作成するときに、次の追加属性を使用することができます:
        //
        //クラスの最初のテストを実行する前にコードを実行するには、ClassInitialize を使用
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //クラスのすべてのテストを実行した後にコードを実行するには、ClassCleanup を使用
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //各テストを実行する前にコードを実行するには、TestInitialize を使用
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //各テストを実行した後にコードを実行するには、TestCleanup を使用
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        private TwitterCachingConnection testConnection = new TwitterCachingConnection(@"Data Source=|DataDirectory|\TwitterModel.sdf");
        private TwitterCommand command = new TwitterCommand()
        {
            Connection = new TwitterConnection()
            {
                ConsumerKey = "8UwTJZJMJjl4uLZduYvA",
                ConsumerSecret = "eCnmRK0mDSXfjm95j947iixyDaUY3OZleSdkWMhLc",
                Token = "141500207-0sEjrUZwRXujtATsDh4gFSAX3qhCVycqJBtDiWuq",
                TokenSecret = "jZZKmbXhJzh933Eg84P7bEIjNBbp3uNM3q52i8CwU",
            }
        };

        private User getCurrentUserByCommand()
        {
            if (this.command.CurrentUser == null)
            {
                var caching = new TwitterCaching(this.testConnection);

                this.command.VerifyCredentials();
                caching.UpdateUsers(new User[] { this.command.CurrentUser });

                var friends = this.command.Friends(this.command.CurrentUser);
                var followers = this.command.Followers(this.command.CurrentUser);
                caching.UpdateUsers(friends);
                caching.UpdateUsers(followers);

                this.command.CurrentUser.Friends = new List<User>(friends);
                this.command.CurrentUser.Followers = new List<User>(followers);

                caching.UpdateUserFollowers(this.command.CurrentUser.UserID, this.command.CurrentUser.Followers);
                caching.UpdateUserFriends(this.command.CurrentUser.UserID, this.command.CurrentUser.Friends);

            }

            return this.command.CurrentUser;
        }

        private void Enumerate(IEnumerable<TwitterData> datas)
        {
            if (datas == null)
                return;
            foreach (var data in datas)
                Console.WriteLine(data.ToString());
        }

        private void CheckArray(IEnumerable<TwitterData> A, IEnumerable<TwitterData> B)
        {
            if (A.Count() != B.Count())
                Assert.Fail("A.Count() is Not equal to B.Count() ");
            foreach (var item in A)
            {
                Console.WriteLine(item.ToString());
                Assert.IsTrue(B.Contains(item));
            }
        }

        private void CheckTimeline(TwitterLocalCommand targetProv, ITwitterCommand sampleProv, Func<ITwitterCommand, TimelineOption, Timeline> method)
        {
            var act = new Func<TimelineOption, Timeline>((option) =>
            {
                var timeline = method(sampleProv, option);
                targetProv.UpdateStatuses(timeline);

                Timeline actual;
                actual = method(targetProv, option);

                Console.WriteLine("Timeline");
                Enumerate(timeline);
                Console.WriteLine("Actual");
                Enumerate(actual);
                Console.WriteLine("Check");
                CheckArray(timeline, actual);
                Console.WriteLine();

                return timeline;
            });
            TimelineOption optA = new TimelineOption();
            optA.UserID = getCurrentUserByCommand().UserID;
            var result = act(optA);

            var optB = new TimelineOption()
            {
                Count = 50,
                MaxID = result.ToArray()[1].StatusID,
                SinceID = result.ToArray()[3].StatusID,
                UserID = getCurrentUserByCommand().UserID,
            };
            act(optB);

        }

        /// <summary>
        ///TwitterLocalCommand コンストラクター のテスト
        ///</summary>
        [TestMethod()]
        public void TwitterLocalCommandConstructorTest()
        {
            TwitterCachingConnection conn = testConnection;
            TwitterLocalCommand target = new TwitterLocalCommand(conn);
        }

        /// <summary>
        ///TwitterLocalCommand コンストラクター のテスト
        ///</summary>
        [TestMethod()]
        public void TwitterLocalCommandConstructorTest1()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);
        }

        /// <summary>
        ///DestroyStatus のテスト
        ///</summary>
        [TestMethod()]
        public void DestroyStatusTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);
            var testTimeline = this.command.GetHomeTimeline(new TimelineOption() { Count = 1 });
            target.UpdateStatuses(testTimeline);
            long statusID = testTimeline.First().StatusID;
            Timeline actual;
            actual = target.DestroyStatus(statusID);
            Enumerate(actual);

        }

        /// <summary>
        ///Followers のテスト
        ///</summary>
        [TestMethod()]
        public void FollowersTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);
            UserListOption option = new UserListOption() { User = getCurrentUserByCommand() };
            UserList actual;
            actual = target.Followers(option);
            Enumerate(actual);

        }

        /// <summary>
        ///Friends のテスト
        ///</summary>
        [TestMethod()]
        public void FriendsTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);
            UserListOption option = new UserListOption() { User = getCurrentUserByCommand() };
            UserList actual;
            actual = target.Friends(option);
            Enumerate(actual);

        }

        /// <summary>
        ///GetDirectMessages のテスト
        ///</summary>
        [TestMethod()]
        public void GetDirectMessagesTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);
            DirectMessageOption option = new DirectMessageOption();
            DirectMessageCollection actual;
            actual = target.GetDirectMessages(option);
            Enumerate(actual);

        }

        /// <summary>
        ///GetFriendsTimeline のテスト
        ///</summary>
        [TestMethod()]
        public void GetFriendsTimelineTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);

            CheckTimeline(target, command, (cmd, option) => cmd.GetFriendsTimeline(option));
        }

        /// <summary>
        ///GetHomeTimeline のテスト
        ///</summary>
        [TestMethod()]
        public void GetHomeTimelineTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);
            
            CheckTimeline(target, command, (cmd, option) => cmd.GetHomeTimeline(option));
        }

        /// <summary>
        ///GetMentionsTimeline のテスト
        ///</summary>
        [TestMethod()]
        public void GetMentionsTimelineTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);

            CheckTimeline(target, command, (cmd, option) => cmd.GetMentionsTimeline(option));

        }

        /// <summary>
        ///GetSentDirectMessages のテスト
        ///</summary>
        [TestMethod()]
        public void GetSentDirectMessagesTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);
            DirectMessageOption option = new DirectMessageOption();

            var sample = command.GetSentDirectMessages(option);
            target.UpdateDirectMessages(sample);

            DirectMessageCollection actual;
            actual = target.GetSentDirectMessages(option);

            Console.WriteLine("DirectMessages");
            Enumerate(sample);
            Console.WriteLine("actual");
            Enumerate(actual);
            CheckArray(sample, actual);

        }

        /// <summary>
        ///GetRepliesTimeline のテスト
        ///</summary>
        [TestMethod()]
        public void GetRepliesTimelineTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);

            CheckTimeline(target, command, (cmd, option) => cmd.GetRepliesTimeline(option));
        }

        /// <summary>
        ///GetUserTimeline のテスト
        ///</summary>
        [TestMethod()]
        public void GetUserTimelineTest()
        {
            TwitterCachingConnection conn = testConnection;
            User currentUser = this.getCurrentUserByCommand();
            TwitterLocalCommand target = new TwitterLocalCommand(conn, currentUser);

            CheckTimeline(target, command, (cmd, option) => cmd.GetUserTimeline(option));
        }

    }
}
